home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / WaveTableObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  36.2 KB  |  1,209 lines  |  [TEXT/KAHL]

  1. /* WaveTableObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "WaveTableObject.h"
  31. #include "Array.h"
  32. #include "WaveTableList.h"
  33. #include "Memory.h"
  34. #include "DataMunging.h"
  35. #include "FixedPoint.h"
  36. #include "WaveTableWindow.h"
  37. #include "WaveTableStorage.h"
  38. #include "BufferedFileInput.h"
  39. #include "BufferedFileOutput.h"
  40. #include "BinaryCodedDecimal.h"
  41.  
  42.  
  43. struct WaveTableObjectRec
  44.     {
  45.         MyBoolean                                DataModified;
  46.  
  47.         char*                                        Name;
  48.         WaveTableStorageRec*        WaveTableData;
  49.         char*                                        WaveTableFormula;
  50.         double                                    TestAttackDuration;
  51.         double                                    TestDecayDuration;
  52.         double                                    TestFrequency;
  53.         long                                        TestSamplingRate;
  54.  
  55.         WaveTableWindowRec*            WaveTableWindow;
  56.  
  57.         struct CodeCenterRec*        CodeCenter;
  58.         struct MainWindowRec*        MainWindow;
  59.         WaveTableListRec*                WaveTableList;
  60.  
  61.         short                                        SavedWindowXLoc;
  62.         short                                        SavedWindowYLoc;
  63.         short                                        SavedWindowWidth;
  64.         short                                        SavedWindowHeight;
  65.     };
  66.  
  67.  
  68. /* create a new wave table object with reasonable defaults. */
  69. WaveTableObjectRec*        NewWaveTableObject(struct CodeCenterRec* CodeCenter,
  70.                                                 struct MainWindowRec* MainWindow,
  71.                                                 struct WaveTableListRec* WaveTableList)
  72.     {
  73.         WaveTableObjectRec*    WaveTableObj;
  74.  
  75.         WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
  76.             "WaveTableObjectRec");
  77.         if (WaveTableObj == NIL)
  78.             {
  79.              FailurePoint1:
  80.                 return NIL;
  81.             }
  82.         WaveTableObj->DataModified = False;
  83.         WaveTableObj->WaveTableWindow = NIL;
  84.         WaveTableObj->CodeCenter = CodeCenter;
  85.         WaveTableObj->MainWindow = MainWindow;
  86.         WaveTableObj->WaveTableList = WaveTableList;
  87.         WaveTableObj->TestAttackDuration = 1;
  88.         WaveTableObj->TestDecayDuration = 2;
  89.         WaveTableObj->TestFrequency = 261.625565300598635;
  90.         WaveTableObj->TestSamplingRate = 22050;
  91.         WaveTableObj->SavedWindowXLoc = 0;
  92.         WaveTableObj->SavedWindowYLoc = 0;
  93.         WaveTableObj->SavedWindowWidth = 0;
  94.         WaveTableObj->SavedWindowHeight = 0;
  95.         WaveTableObj->Name = StringToBlockCopy("untitled");
  96.         if (WaveTableObj->Name == NIL)
  97.             {
  98.              FailurePoint2:
  99.                 ReleasePtr((char*)WaveTableObj);
  100.                 goto FailurePoint1;
  101.             }
  102.         WaveTableObj->WaveTableFormula = StringToBlockCopy(
  103.             "# data : fixedarray; frames : integer; tables : integer\x0a");
  104.         if (WaveTableObj->WaveTableFormula == NIL)
  105.             {
  106.              FailurePoint3:
  107.                 ReleasePtr(WaveTableObj->Name);
  108.                 goto FailurePoint2;
  109.             }
  110.         WaveTableObj->WaveTableData = NewWaveTableStorage(eSample16bit,256);
  111.         if (WaveTableObj->WaveTableData == NIL)
  112.             {
  113.              FailurePoint4:
  114.                 ReleasePtr(WaveTableObj->WaveTableFormula);
  115.                 goto FailurePoint3;
  116.             }
  117.         return WaveTableObj;
  118.     }
  119.  
  120.  
  121. /* create a new wave table based on the data being passed in. */
  122. WaveTableObjectRec*        NewWaveTableObjectFromData(struct CodeCenterRec* CodeCenter,
  123.                                                 struct MainWindowRec* MainWindow,
  124.                                                 struct WaveTableListRec* WaveTableList, char* RawData,
  125.                                                 NumBitsType NumBits, long NumTables, long FramesPerTable)
  126.     {
  127.         long                                Scan;
  128.         WaveTableObjectRec*    WaveTableObj;
  129.  
  130.         WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
  131.             "WaveTableObjectRec");
  132.         if (WaveTableObj == NIL)
  133.             {
  134.              FailurePoint1:
  135.                 return NIL;
  136.             }
  137.         WaveTableObj->DataModified = False;
  138.         WaveTableObj->WaveTableWindow = NIL;
  139.         WaveTableObj->CodeCenter = CodeCenter;
  140.         WaveTableObj->MainWindow = MainWindow;
  141.         WaveTableObj->WaveTableList = WaveTableList;
  142.         WaveTableObj->TestAttackDuration = 1;
  143.         WaveTableObj->TestDecayDuration = 2;
  144.         WaveTableObj->TestFrequency = 261.625565300598635;
  145.         WaveTableObj->TestSamplingRate = 22050;
  146.         WaveTableObj->SavedWindowXLoc = 0;
  147.         WaveTableObj->SavedWindowYLoc = 0;
  148.         WaveTableObj->SavedWindowWidth = 0;
  149.         WaveTableObj->SavedWindowHeight = 0;
  150.         WaveTableObj->Name = StringToBlockCopy("AlgoWaveTable Copy");
  151.         if (WaveTableObj->Name == NIL)
  152.             {
  153.              FailurePoint2:
  154.                 ReleasePtr((char*)WaveTableObj);
  155.                 goto FailurePoint1;
  156.             }
  157.         WaveTableObj->WaveTableFormula = StringToBlockCopy(
  158.             "# data : fixedarray; frames : integer; tables : integer\x0a");
  159.         if (WaveTableObj->WaveTableFormula == NIL)
  160.             {
  161.              FailurePoint3:
  162.                 ReleasePtr(WaveTableObj->Name);
  163.                 goto FailurePoint2;
  164.             }
  165.         WaveTableObj->WaveTableData = NewWaveTableStorage(NumBits,FramesPerTable);
  166.         if (WaveTableObj->WaveTableData == NIL)
  167.             {
  168.              FailurePoint4:
  169.                 ReleasePtr(WaveTableObj->WaveTableFormula);
  170.                 goto FailurePoint3;
  171.             }
  172.         for (Scan = 0; Scan < NumTables; Scan += 1)
  173.             {
  174.                 if (!WaveTableStorageAppendEntry(WaveTableObj->WaveTableData))
  175.                     {
  176.                      FailurePoint5:
  177.                         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  178.                         goto FailurePoint4;
  179.                     }
  180.             }
  181.         for (Scan = 0; Scan < NumTables; Scan += 1)
  182.             {
  183.                 long                        Index;
  184.  
  185.                 switch (NumBits)
  186.                     {
  187.                         default:
  188.                             EXECUTE(PRERR(ForceAbort,"NewWaveTableObjectFromData:  bad NumBits"));
  189.                             break;
  190.                         case eSample8bit:
  191.                             for (Index = 0; Index < FramesPerTable; Index += 1)
  192.                                 {
  193.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,
  194.                                         Index,double2largefixed(
  195.                                         ((double)(((signed char*)RawData)[Scan * FramesPerTable + Index]))
  196.                                         / MAX8BIT));
  197.                                 }
  198.                             break;
  199.                         case eSample16bit:
  200.                             for (Index = 0; Index < FramesPerTable; Index += 1)
  201.                                 {
  202.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,
  203.                                         Index,double2largefixed(
  204.                                         ((double)(((signed short*)RawData)[Scan * FramesPerTable + Index]))
  205.                                         / MAX16BIT));
  206.                                 }
  207.                             break;
  208.                     }
  209.             }
  210.         return WaveTableObj;
  211.     }
  212.  
  213.  
  214. /* dispose of a wave table object */
  215. void                                    DisposeWaveTableObject(WaveTableObjectRec* WaveTableObj)
  216.     {
  217.         CheckPtrExistence(WaveTableObj);
  218.         if (WaveTableObj->WaveTableWindow != NIL)
  219.             {
  220.                 DisposeWaveTableWindow(WaveTableObj->WaveTableWindow);
  221.                 ERROR(WaveTableObj->WaveTableWindow != NIL,PRERR(ForceAbort,
  222.                     "DisposeWaveTableObject:  disposed window but it isn't NIL"));
  223.             }
  224.         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  225.         ReleasePtr(WaveTableObj->Name);
  226.         ReleasePtr(WaveTableObj->WaveTableFormula);
  227.         ReleasePtr((char*)WaveTableObj);
  228.     }
  229.  
  230.  
  231. /* find out if wave table object has been modified */
  232. MyBoolean                            HasWaveTableObjectBeenModified(WaveTableObjectRec* WaveTableObj)
  233.     {
  234.         CheckPtrExistence(WaveTableObj);
  235.         if (WaveTableObj->WaveTableWindow != NIL)
  236.             {
  237.                 return WaveTableObj->DataModified
  238.                     || HasWaveTableWindowBeenModified(WaveTableObj->WaveTableWindow);
  239.             }
  240.          else
  241.             {
  242.                 return WaveTableObj->DataModified;
  243.             }
  244.     }
  245.  
  246.  
  247. /* get a copy of the wave table's name */
  248. char*                                    WaveTableObjectGetNameCopy(WaveTableObjectRec* WaveTableObj)
  249.     {
  250.         char*                                NameTemp;
  251.  
  252.         CheckPtrExistence(WaveTableObj);
  253.         if (WaveTableObj->WaveTableWindow != NIL)
  254.             {
  255.                 NameTemp = WaveTableWindowGetNameCopy(WaveTableObj->WaveTableWindow);
  256.             }
  257.          else
  258.             {
  259.                 NameTemp = CopyPtr(WaveTableObj->Name);
  260.             }
  261.         if (NameTemp != NIL)
  262.             {
  263.                 SetTag(NameTemp,"WaveTableNameCopy");
  264.             }
  265.         return NameTemp;
  266.     }
  267.  
  268.  
  269. /* set the wave table's name.  the object becomes the owner of the Name block, */
  270. /* so the caller should not release it. */
  271. void                                    WaveTableObjectNewName(WaveTableObjectRec* WaveTableObj,
  272.                                                 char* Name)
  273.     {
  274.         CheckPtrExistence(WaveTableObj);
  275.         CheckPtrExistence(Name);
  276.         ReleasePtr(WaveTableObj->Name);
  277.         SetTag(Name,"WaveTableName");
  278.         WaveTableObj->Name = Name;
  279.         WaveTableObj->DataModified = True;
  280.         WaveTableListWaveTableNameChanged(WaveTableObj->WaveTableList,WaveTableObj);
  281.     }
  282.  
  283.  
  284. /* get a copy of the formula applied to the wave table. */
  285. char*                                    WaveTableObjectGetFormulaCopy(WaveTableObjectRec* WaveTableObj)
  286.     {
  287.         char*                                TextCopy;
  288.  
  289.         CheckPtrExistence(WaveTableObj);
  290.         if (WaveTableObj->WaveTableWindow != NIL)
  291.             {
  292.                 TextCopy = WaveTableWindowGetFormulaCopy(WaveTableObj->WaveTableWindow);
  293.             }
  294.          else
  295.             {
  296.                 TextCopy = CopyPtr(WaveTableObj->WaveTableFormula);
  297.             }
  298.         if (TextCopy != NIL)
  299.             {
  300.                 SetTag(TextCopy,"WaveTableFormulaCopy");
  301.             }
  302.         return TextCopy;
  303.     }
  304.  
  305.  
  306. /* install a new formula into the wave table.  the object becomes the owner of */
  307. /* the formula, so the caller should not dispose it. */
  308. void                                    WaveTableObjectNewFormula(WaveTableObjectRec* WaveTableObj,
  309.                                                 char* Formula)
  310.     {
  311.         CheckPtrExistence(WaveTableObj);
  312.         CheckPtrExistence(Formula);
  313.         ReleasePtr(WaveTableObj->WaveTableFormula);
  314.         SetTag(Formula,"WaveTableFormula");
  315.         WaveTableObj->WaveTableFormula = Formula;
  316.         WaveTableObj->DataModified = True;
  317.     }
  318.  
  319.  
  320. /* find out whether its 8 or 16 bits. */
  321. NumBitsType                        WaveTableObjectGetNumBits(WaveTableObjectRec* WaveTableObj)
  322.     {
  323.         CheckPtrExistence(WaveTableObj);
  324.         if (WaveTableObj->WaveTableWindow != NIL)
  325.             {
  326.                 return WaveTableWindowGetNumBits(WaveTableObj->WaveTableWindow);
  327.             }
  328.          else
  329.             {
  330.                 return WaveTableStorageNumBits(WaveTableObj->WaveTableData);
  331.             }
  332.     }
  333.  
  334.  
  335. /* find out how many tables there are in the wave table */
  336. long                                    WaveTableObjectGetNumTables(WaveTableObjectRec* WaveTableObj)
  337.     {
  338.         CheckPtrExistence(WaveTableObj);
  339.         if (WaveTableObj->WaveTableWindow != NIL)
  340.             {
  341.                 return WaveTableWindowGetNumTables(WaveTableObj->WaveTableWindow);
  342.             }
  343.          else
  344.             {
  345.                 return WaveTableStorageNumTables(WaveTableObj->WaveTableData);
  346.             }
  347.     }
  348.  
  349.  
  350. /* find out how many entries there are in a single table */
  351. long                                    WaveTableObjectEntriesPerTable(WaveTableObjectRec* WaveTableObj)
  352.     {
  353.         CheckPtrExistence(WaveTableObj);
  354.         if (WaveTableObj->WaveTableWindow != NIL)
  355.             {
  356.                 return WaveTableWindowGetNumFramesPerTable(WaveTableObj->WaveTableWindow);
  357.             }
  358.          else
  359.             {
  360.                 return WaveTableStorageNumFramesPerTable(WaveTableObj->WaveTableData);
  361.             }
  362.     }
  363.  
  364.  
  365. /* get the raw data for a particular wave table.  this returns the actual data, so */
  366. /* don't dispose it.  if any operations are performed on the wave table, this */
  367. /* pointer may become invalid.  the data is in the following format: */
  368. /*  - 8-bit:  array of signed bytes */
  369. /*  - 16-bit:  array of signed short integers */
  370. char*                                    WaveTableObjectGetRawSlice(WaveTableObjectRec* WaveTableObj,
  371.                                                 long WaveTableIndex)
  372.     {
  373.         CheckPtrExistence(WaveTableObj);
  374.         ERROR((WaveTableIndex < 0) || (WaveTableIndex
  375.             >= WaveTableObjectGetNumTables(WaveTableObj)),PRERR(ForceAbort,
  376.             "WaveTableObjectGetRawSlice:  index out of range"));
  377.         if (WaveTableObj->WaveTableWindow != NIL)
  378.             {
  379.                 if (!WaveTableWindowForceWaveTableUpdate(WaveTableObj->WaveTableWindow))
  380.                     {
  381.                         return NIL;
  382.                     }
  383.             }
  384.         return (char*)WaveTableStorageGetTable(WaveTableObj->WaveTableData,WaveTableIndex);
  385.     }
  386.  
  387.  
  388. /* put new data into the wave table. the object becomes the owner of all data passed in. */
  389. void                                    WaveTableObjectPutNewData(WaveTableObjectRec* WaveTableObj,
  390.                                                 struct WaveTableStorageRec* NewWaveTable)
  391.     {
  392.         CheckPtrExistence(WaveTableObj);
  393.         CheckPtrExistence(NewWaveTable);
  394.         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  395.         WaveTableObj->WaveTableData = NewWaveTable;
  396.         WaveTableObj->DataModified = True;
  397.     }
  398.  
  399.  
  400. /* tell the wave table to open it's editor window */
  401. MyBoolean                            WaveTableObjectOpenWindow(WaveTableObjectRec* WaveTableObj)
  402.     {
  403.         CheckPtrExistence(WaveTableObj);
  404.         if (WaveTableObj->WaveTableWindow == NIL)
  405.             {
  406.                 WaveTableObj->WaveTableWindow = NewWaveTableWindow(WaveTableObj->MainWindow,
  407.                     WaveTableObj,WaveTableObj->CodeCenter,WaveTableObj->WaveTableList,
  408.                     WaveTableObj->WaveTableData,WaveTableObj->SavedWindowXLoc,
  409.                     WaveTableObj->SavedWindowYLoc,WaveTableObj->SavedWindowWidth,
  410.                     WaveTableObj->SavedWindowHeight);
  411.             }
  412.          else
  413.             {
  414.                 WaveTableWindowBringToTop(WaveTableObj->WaveTableWindow);
  415.             }
  416.         return (WaveTableObj->WaveTableWindow != NIL);
  417.     }
  418.  
  419.  
  420. /* this is called by the window when it is closing to notify the object. */
  421. /* the object should not take any action. */
  422. void                                    WaveTableObjectClosingWindowNotify(
  423.                                                 WaveTableObjectRec* WaveTableObj, short NewX, short NewY,
  424.                                                 short NewWidth, short NewHeight)
  425.     {
  426.         CheckPtrExistence(WaveTableObj);
  427.         ERROR(WaveTableObj->WaveTableWindow == NIL,PRERR(ForceAbort,
  428.             "WaveTableObjectClosingWindowNotify:  window not open"));
  429.         WaveTableObj->WaveTableWindow = NIL;
  430.         WaveTableObj->SavedWindowXLoc = NewX;
  431.         WaveTableObj->SavedWindowYLoc = NewY;
  432.         WaveTableObj->SavedWindowWidth = NewWidth;
  433.         WaveTableObj->SavedWindowHeight = NewHeight;
  434.     }
  435.  
  436.  
  437. /* obtain a fixedpoint array of data.  NIL is returned if there isn't enough memory. */
  438. largefixedsigned*            WaveTableObjectGetFixed(WaveTableObjectRec* WaveTableObj)
  439.     {
  440.         largefixedsigned*        Array;
  441.  
  442.         CheckPtrExistence(WaveTableObj);
  443.         if (WaveTableObj->WaveTableWindow == NIL)
  444.             {
  445.                 long                                TableLimit;
  446.                 long                                FrameLimit;
  447.                 long                                TableScan;
  448.  
  449.                 TableLimit = WaveTableObjectGetNumTables(WaveTableObj);
  450.                 FrameLimit = WaveTableObjectEntriesPerTable(WaveTableObj);
  451.                 Array = (largefixedsigned*)AllocPtrCanFail(TableLimit * FrameLimit
  452.                     * sizeof(largefixedsigned),"WaveTableFixedArrayCopy");
  453.                 if (Array != NIL)
  454.                     {
  455.                         for (TableScan = 0; TableScan < TableLimit; TableScan += 1)
  456.                             {
  457.                                 long                                FrameScan;
  458.  
  459.                                 for (FrameScan = 0; FrameScan < FrameLimit; FrameScan += 1)
  460.                                     {
  461.                                         PRNGCHK(Array,&(Array[TableScan * FrameLimit + FrameScan]),
  462.                                             sizeof(Array[TableScan * FrameLimit + FrameScan]));
  463.                                         Array[TableScan * FrameLimit + FrameScan]
  464.                                             = WaveTableStorageGetFrame(WaveTableObj->WaveTableData,
  465.                                             TableScan,FrameScan);
  466.                                     }
  467.                             }
  468.                     }
  469.             }
  470.          else
  471.             {
  472.                 Array = WaveTableWindowGetWaveArray(WaveTableObj->WaveTableWindow);
  473.             }
  474.         return Array;
  475.     }
  476.  
  477.  
  478. /* the document's name has changed, so we need to update the windows */
  479. void                                    WaveTableObjectGlobalNameChange(WaveTableObjectRec* WaveTableObj,
  480.                                                 char* NewFilename)
  481.     {
  482.         CheckPtrExistence(WaveTableObj);
  483.         if (WaveTableObj->WaveTableWindow != NIL)
  484.             {
  485.                 WaveTableWindowGlobalNameChange(WaveTableObj->WaveTableWindow,NewFilename);
  486.             }
  487.     }
  488.  
  489.  
  490. /* get the test attack duration */
  491. double                                WaveTableObjectGetTestAttack(WaveTableObjectRec* WaveTableObj)
  492.     {
  493.         CheckPtrExistence(WaveTableObj);
  494.         if (WaveTableObj->WaveTableWindow != NIL)
  495.             {
  496.                 return WaveTableWindowGetAscendingDuration(WaveTableObj->WaveTableWindow);
  497.             }
  498.          else
  499.             {
  500.                 return WaveTableObj->TestAttackDuration;
  501.             }
  502.     }
  503.  
  504.  
  505. /* put a new test attack duration */
  506. void                                    SetWaveTableObjectTestAttack(WaveTableObjectRec* WaveTableObj,
  507.                                                 double NewTestAttack)
  508.     {
  509.         CheckPtrExistence(WaveTableObj);
  510.         WaveTableObj->TestAttackDuration = NewTestAttack;
  511.     }
  512.  
  513.  
  514. /* get the test decay duration */
  515. double                                WaveTableObjectGetTestDecay(WaveTableObjectRec* WaveTableObj)
  516.     {
  517.         CheckPtrExistence(WaveTableObj);
  518.         if (WaveTableObj->WaveTableWindow != NIL)
  519.             {
  520.                 return WaveTableWindowGetDescendingDuration(WaveTableObj->WaveTableWindow);
  521.             }
  522.          else
  523.             {
  524.                 return WaveTableObj->TestDecayDuration;
  525.             }
  526.     }
  527.  
  528.  
  529. /* put a new test decay duration */
  530. void                                    SetWaveTableObjectTestDecay(WaveTableObjectRec* WaveTableObj,
  531.                                                 double NewTestDecay)
  532.     {
  533.         CheckPtrExistence(WaveTableObj);
  534.         WaveTableObj->TestDecayDuration = NewTestDecay;
  535.     }
  536.  
  537.  
  538. /* get the test sampling rate */
  539. long                                    WaveTableObjectGetTestSamplingRate(WaveTableObjectRec* WaveTableObj)
  540.     {
  541.         CheckPtrExistence(WaveTableObj);
  542.         if (WaveTableObj->WaveTableWindow != NIL)
  543.             {
  544.                 return WaveTableWindowGetTestSamplingRate(WaveTableObj->WaveTableWindow);
  545.             }
  546.          else
  547.             {
  548.                 return WaveTableObj->TestSamplingRate;
  549.             }
  550.     }
  551.  
  552.  
  553. /* put a new test sampling rate */
  554. void                                    SetWaveTableObjectTestSamplingRate(WaveTableObjectRec* WaveTableObj,
  555.                                                 long NewTestSamplingRate)
  556.     {
  557.         CheckPtrExistence(WaveTableObj);
  558.         WaveTableObj->TestSamplingRate = NewTestSamplingRate;
  559.     }
  560.  
  561.  
  562. /* get the test pitch */
  563. double                                WaveTableObjectGetTestPitch(WaveTableObjectRec* WaveTableObj)
  564.     {
  565.         CheckPtrExistence(WaveTableObj);
  566.         if (WaveTableObj->WaveTableWindow != NIL)
  567.             {
  568.                 return WaveTableWindowGetPitch(WaveTableObj->WaveTableWindow);
  569.             }
  570.          else
  571.             {
  572.                 return WaveTableObj->TestFrequency;
  573.             }
  574.     }
  575.  
  576.  
  577. /* put a new test pitch */
  578. void                                    SetWaveTableObjectTestPitch(WaveTableObjectRec* WaveTableObj,
  579.                                                 double NewTestPitch)
  580.     {
  581.         CheckPtrExistence(WaveTableObj);
  582.         WaveTableObj->TestFrequency = NewTestPitch;
  583.     }
  584.  
  585.  
  586. /* Wave Table Object Subblock Format: */
  587. /*   1-byte format version number */
  588. /*       should be 1 */
  589. /*   2-byte little endian window X location (signed; origin at upper left corner) */
  590. /*   2-byte little endian window Y location */
  591. /*   2-byte little endian window width */
  592. /*   2-byte little endian window height */
  593. /*   4-byte little endian wave table name length descriptor */
  594. /*   n-byte name string (line feed = 0x0a) */
  595. /*   4-byte little endian wave table formula length descriptor */
  596. /*   n-byte formula string (line feed = 0x0a) */
  597. /*   4-byte little endian large integer encoded test attack duration. */
  598. /*       large integer coded decimal is decimal * 1000000 with a */
  599. /*       range of -1999.999999 to 1999.999999 */
  600. /*   4-byte little endian large integer encoded test decay duration. */
  601. /*   4-byte little endian test frequency fractional portion */
  602. /*       unsigned; divide by 2^32 to get the actual fraction */
  603. /*   4-byte little endian test frequency integer portion */
  604. /*       total test frequency should be between 0.01 and 1e6 */
  605. /*   4-byte little endian test sampling rate */
  606. /*       should be between 100 and 65535 */
  607. /*   4-byte little endian number of tables */
  608. /*   4-byte little endian number of frames per table */
  609. /*       must be an integral power or 2 between 2 and 65536 */
  610. /*   1-byte number of bits specifier */
  611. /*       must be 8 or 16 */
  612. /*   n-byte sample data for the wave table */
  613. /*       data is stored as follows:  each table is stored consecutively starting */
  614. /*       with the table numbered 0.  in each table, each sample frame is stored */
  615. /*       consecutively as a signed 2s complement value.  8-bit sample frames */
  616. /*       use 1 byte each.  16-bit sample frames use 2 bytes and are stored little */
  617. /*       endian. */
  618.  
  619.  
  620. /* load an object from the file */
  621. FileLoadingErrors            WaveTableObjectNewFromFile(WaveTableObjectRec** ObjectOut,
  622.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  623.                                                 struct MainWindowRec* MainWindow,
  624.                                                 struct WaveTableListRec* WaveTableList)
  625.     {
  626.         unsigned char                UnsignedChar;
  627.         WaveTableObjectRec*    WaveTableObj;
  628.         FileLoadingErrors        Error;
  629.         signed short                SignedShort;
  630.         unsigned long                UnsignedLong;
  631.         signed long                    SignedLong;
  632.         signed long                    NumberOfTables;
  633.         signed long                    NumberOfFrames;
  634.         NumBitsType                    NumberOfBits;
  635.         long                                Scan;
  636.  
  637.         CheckPtrExistence(Input);
  638.         CheckPtrExistence(CodeCenter);
  639.         CheckPtrExistence(MainWindow);
  640.         CheckPtrExistence(WaveTableList);
  641.  
  642.         WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
  643.             "WaveTableObjectRec");
  644.         if (WaveTableObj == NIL)
  645.             {
  646.                 Error = eFileLoadOutOfMemory;
  647.              FailurePoint1:
  648.                 return Error;
  649.             }
  650.  
  651.         /*   1-byte format version number */
  652.         /*       should be 1 */
  653.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  654.             {
  655.                 Error = eFileLoadDiskError;
  656.              FailurePoint2:
  657.                 ReleasePtr((char*)WaveTableObj);
  658.                 goto FailurePoint1;
  659.             }
  660.         if (UnsignedChar != 1)
  661.             {
  662.                 Error = eFileLoadBadFormat;
  663.              FailurePoint3:
  664.                 goto FailurePoint2;
  665.             }
  666.  
  667.         /*   2-byte little endian window X location (signed; origin at upper left corner) */
  668.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  669.             {
  670.                 Error = eFileLoadDiskError;
  671.              FailurePoint4:
  672.                 goto FailurePoint3;
  673.             }
  674.         WaveTableObj->SavedWindowXLoc = SignedShort;
  675.  
  676.         /*   2-byte little endian window Y location */
  677.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  678.             {
  679.                 Error = eFileLoadDiskError;
  680.              FailurePoint5:
  681.                 goto FailurePoint4;
  682.             }
  683.         WaveTableObj->SavedWindowYLoc = SignedShort;
  684.  
  685.         /*   2-byte little endian window width */
  686.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  687.             {
  688.                 Error = eFileLoadDiskError;
  689.              FailurePoint6:
  690.                 goto FailurePoint5;
  691.             }
  692.         WaveTableObj->SavedWindowWidth = SignedShort;
  693.  
  694.         /*   2-byte little endian window height */
  695.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  696.             {
  697.                 Error = eFileLoadDiskError;
  698.              FailurePoint7:
  699.                 goto FailurePoint6;
  700.             }
  701.         WaveTableObj->SavedWindowHeight = SignedShort;
  702.  
  703.         /*   4-byte little endian wave table name length descriptor */
  704.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  705.             {
  706.                 Error = eFileLoadDiskError;
  707.              FailurePoint8:
  708.                 goto FailurePoint7;
  709.             }
  710.         if (SignedLong < 0)
  711.             {
  712.                 Error = eFileLoadBadFormat;
  713.              FailurePoint9:
  714.                 goto FailurePoint8;
  715.             }
  716.  
  717.         /*   n-byte name string (line feed = 0x0a) */
  718.         WaveTableObj->Name = AllocPtrCanFail(SignedLong,"WaveTableObjectRec:  name");
  719.         if (WaveTableObj->Name == NIL)
  720.             {
  721.                 Error = eFileLoadOutOfMemory;
  722.              FailurePoint10:
  723.                 goto FailurePoint9;
  724.             }
  725.         if (!ReadBufferedInput(Input,SignedLong,WaveTableObj->Name))
  726.             {
  727.                 Error = eFileLoadDiskError;
  728.              FailurePoint11:
  729.                 ReleasePtr(WaveTableObj->Name);
  730.                 goto FailurePoint10;
  731.             }
  732.  
  733.         /*   4-byte little endian wave table formula length descriptor */
  734.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  735.             {
  736.                 Error = eFileLoadDiskError;
  737.              FailurePoint12:
  738.                 goto FailurePoint11;
  739.             }
  740.         if (SignedLong < 0)
  741.             {
  742.                 Error = eFileLoadBadFormat;
  743.              FailurePoint13:
  744.                 goto FailurePoint12;
  745.             }
  746.  
  747.         /*   n-byte formula string (line feed = 0x0a) */
  748.         WaveTableObj->WaveTableFormula = AllocPtrCanFail(SignedLong,
  749.             "WaveTableObjectRec:  formula");
  750.         if (WaveTableObj->WaveTableFormula == NIL)
  751.             {
  752.                 Error = eFileLoadOutOfMemory;
  753.              FailurePoint14:
  754.                 goto FailurePoint13;
  755.             }
  756.         if (!ReadBufferedInput(Input,SignedLong,WaveTableObj->WaveTableFormula))
  757.             {
  758.                 Error = eFileLoadDiskError;
  759.              FailurePoint15:
  760.                 ReleasePtr(WaveTableObj->WaveTableFormula);
  761.                 goto FailurePoint14;
  762.             }
  763.  
  764.         /*   4-byte little endian large integer encoded test attack duration. */
  765.         /*       large integer coded decimal is decimal * 1000000 with a */
  766.         /*       range of -1999.999999 to 1999.999999 */
  767.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  768.             {
  769.                 Error = eFileLoadDiskError;
  770.              FailurePoint16:
  771.                 goto FailurePoint15;
  772.             }
  773.         WaveTableObj->TestAttackDuration = LargeBCD2Double(SignedLong);
  774.         if (WaveTableObj->TestAttackDuration < 0)
  775.             {
  776.                 WaveTableObj->TestAttackDuration = 0;
  777.             }
  778.  
  779.         /*   4-byte little endian large integer encoded test decay duration. */
  780.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  781.             {
  782.                 Error = eFileLoadDiskError;
  783.              FailurePoint17:
  784.                 goto FailurePoint16;
  785.             }
  786.         WaveTableObj->TestDecayDuration = LargeBCD2Double(SignedLong);
  787.         if (WaveTableObj->TestDecayDuration < 0)
  788.             {
  789.                 WaveTableObj->TestDecayDuration = 0;
  790.             }
  791.  
  792.         /*   4-byte little endian test frequency fractional portion */
  793.         /*       unsigned; divide by 2^32 to get the actual fraction */
  794.         if (!ReadBufferedUnsignedLongLittleEndian(Input,&UnsignedLong))
  795.             {
  796.                 Error = eFileLoadDiskError;
  797.              FailurePoint18:
  798.                 goto FailurePoint17;
  799.             }
  800.         WaveTableObj->TestFrequency = (double)UnsignedLong / 4294967296.0L;
  801.  
  802.         /*   4-byte little endian test frequency integer portion */
  803.         /*       total test frequency should be between 0.01 and 1e6 */
  804.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  805.             {
  806.                 Error = eFileLoadDiskError;
  807.              FailurePoint19:
  808.                 goto FailurePoint18;
  809.             }
  810.         WaveTableObj->TestFrequency += SignedLong;
  811.         if (WaveTableObj->TestFrequency < MINNATURALFREQ)
  812.             {
  813.                 WaveTableObj->TestFrequency = MINNATURALFREQ;
  814.             }
  815.         if (WaveTableObj->TestFrequency > MAXNATURALFREQ)
  816.             {
  817.                 WaveTableObj->TestFrequency = MAXNATURALFREQ;
  818.             }
  819.  
  820.         /*   4-byte little endian test sampling rate */
  821.         /*       should be between 100 and 65535 */
  822.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  823.             {
  824.                 Error = eFileLoadDiskError;
  825.              FailurePoint20:
  826.                 goto FailurePoint19;
  827.             }
  828.         if (SignedLong < MINSAMPLINGRATE)
  829.             {
  830.                 SignedLong = MINSAMPLINGRATE;
  831.             }
  832.         if (SignedLong > MAXSAMPLINGRATE)
  833.             {
  834.                 SignedLong = MAXSAMPLINGRATE;
  835.             }
  836.         WaveTableObj->TestSamplingRate = SignedLong;
  837.  
  838.         /*   4-byte little endian number of tables */
  839.         if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfTables))
  840.             {
  841.                 Error = eFileLoadDiskError;
  842.              FailurePoint21:
  843.                 goto FailurePoint20;
  844.             }
  845.         if (NumberOfTables < 0)
  846.             {
  847.                 Error = eFileLoadBadFormat;
  848.              FailurePoint22:
  849.                 goto FailurePoint21;
  850.             }
  851.  
  852.         /*   4-byte little endian number of frames per table */
  853.         /*       must be an integral power or 2 between 2 and 65536 */
  854.         if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfFrames))
  855.             {
  856.                 Error = eFileLoadDiskError;
  857.              FailurePoint23:
  858.                 goto FailurePoint22;
  859.             }
  860.         if ((NumberOfFrames != 2) && (NumberOfFrames != 4) && (NumberOfFrames != 8)
  861.             && (NumberOfFrames != 16) && (NumberOfFrames != 32) && (NumberOfFrames != 64)
  862.             && (NumberOfFrames != 128) && (NumberOfFrames != 256) && (NumberOfFrames != 512)
  863.             && (NumberOfFrames != 1024) && (NumberOfFrames != 2048)
  864.             && (NumberOfFrames != 4096) && (NumberOfFrames != 8192)
  865.             && (NumberOfFrames != 16384) && (NumberOfFrames != 32768)
  866.             && (NumberOfFrames != 65536))
  867.             {
  868.                 Error = eFileLoadBadFormat;
  869.              FailurePoint24:
  870.                 goto FailurePoint23;
  871.             }
  872.  
  873.         /*   1-byte number of bits specifier */
  874.         /*       must be 8 or 16 */
  875.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  876.             {
  877.                 Error = eFileLoadDiskError;
  878.              FailurePoint25:
  879.                 goto FailurePoint24;
  880.             }
  881.         if (UnsignedChar == 8)
  882.             {
  883.                 NumberOfBits = eSample8bit;
  884.             }
  885.         else if (UnsignedChar == 16)
  886.             {
  887.                 NumberOfBits = eSample16bit;
  888.             }
  889.         else
  890.             {
  891.                 Error = eFileLoadBadFormat;
  892.              FailurePoint26:
  893.                 goto FailurePoint25;
  894.             }
  895.  
  896.         /*   n-byte sample data for the wave table */
  897.         /*       data is stored as follows:  each table is stored consecutively starting */
  898.         /*       with the table numbered 0.  in each table, each sample frame is stored */
  899.         /*       consecutively as a signed 2s complement value.  8-bit sample frames */
  900.         /*       use 1 byte each.  16-bit sample frames use 2 bytes and are stored little */
  901.         /*       endian. */
  902.         WaveTableObj->WaveTableData = NewWaveTableStorage(NumberOfBits,NumberOfFrames);
  903.         if (WaveTableObj->WaveTableData == NIL)
  904.             {
  905.                 Error = eFileLoadOutOfMemory;
  906.              FailurePoint27:
  907.                 goto FailurePoint26;
  908.             }
  909.         for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  910.             {
  911.                 if (!WaveTableStorageAppendEntry(WaveTableObj->WaveTableData))
  912.                     {
  913.                         Error = eFileLoadOutOfMemory;
  914.                      FailurePoint28:
  915.                         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  916.                         goto FailurePoint27;
  917.                     }
  918.             }
  919.         switch (NumberOfBits)
  920.             {
  921.                 default:
  922.                     EXECUTE(PRERR(ForceAbort,"WaveTableObjectNewFromFile:  bad number of bits"));
  923.                     break;
  924.                 case eSample8bit:
  925.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  926.                         {
  927.                             long                            Index;
  928.  
  929.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  930.                                 {
  931.                                     signed char                SamplePoint;
  932.  
  933.                                     if (!ReadBufferedSignedChar(Input,&SamplePoint))
  934.                                         {
  935.                                             Error = eFileLoadDiskError;
  936.                                             goto FailurePoint28;
  937.                                         }
  938.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,Index,
  939.                                         double2largefixed((double)SamplePoint / MAX8BIT));
  940.                                 }
  941.                         }
  942.                     break;
  943.                 case eSample16bit:
  944.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  945.                         {
  946.                             long                            Index;
  947.  
  948.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  949.                                 {
  950.                                     signed short            SamplePoint;
  951.  
  952.                                     if (!ReadBufferedSignedShortLittleEndian(Input,&SamplePoint))
  953.                                         {
  954.                                             Error = eFileLoadDiskError;
  955.                                             goto FailurePoint28;
  956.                                         }
  957.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,Index,
  958.                                         double2largefixed((double)SamplePoint / MAX16BIT));
  959.                                 }
  960.                         }
  961.                     break;
  962.             }
  963.  
  964.         /* fill in the other fields */
  965.         WaveTableObj->DataModified = False;
  966.         WaveTableObj->WaveTableWindow = NIL;
  967.         WaveTableObj->CodeCenter = CodeCenter;
  968.         WaveTableObj->MainWindow = MainWindow;
  969.         WaveTableObj->WaveTableList = WaveTableList;
  970.  
  971.         *ObjectOut = WaveTableObj;
  972.         return eFileLoadNoError;
  973.     }
  974.  
  975.  
  976. /* write the object out to the file. */
  977. FileLoadingErrors            WaveTableObjectWriteDataOut(WaveTableObjectRec* WaveTableObj,
  978.                                                 struct BufferedOutputRec* Output)
  979.     {
  980.         char*                                StringTemp;
  981.         double                            FrequencyTemp;
  982.         long                                NumberOfTables;
  983.         long                                NumberOfFrames;
  984.         NumBitsType                    NumberOfBits;
  985.         long                                Scan;
  986.  
  987.         CheckPtrExistence(WaveTableObj);
  988.         CheckPtrExistence(Output);
  989.  
  990.         if (WaveTableObj->WaveTableWindow != NIL)
  991.             {
  992.                 if (!WaveTableWindowForceWaveTableUpdate(WaveTableObj->WaveTableWindow))
  993.                     {
  994.                         return eFileLoadOutOfMemory;
  995.                     }
  996.             }
  997.  
  998.         /*   1-byte format version number */
  999.         /*       should be 1 */
  1000.         if (!WriteBufferedUnsignedChar(Output,1))
  1001.             {
  1002.                 return eFileLoadDiskError;
  1003.             }
  1004.  
  1005.         /*   2-byte little endian window X location (signed; origin at upper left corner) */
  1006.         /* note that if the window is open when the file is saved, then the most */
  1007.         /* recent coordinates of the window will not be saved */
  1008.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowXLoc))
  1009.             {
  1010.                 return eFileLoadDiskError;
  1011.             }
  1012.  
  1013.         /*   2-byte little endian window Y location */
  1014.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowYLoc))
  1015.             {
  1016.                 return eFileLoadDiskError;
  1017.             }
  1018.  
  1019.         /*   2-byte little endian window width */
  1020.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowWidth))
  1021.             {
  1022.                 return eFileLoadDiskError;
  1023.             }
  1024.  
  1025.         /*   2-byte little endian window height */
  1026.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowHeight))
  1027.             {
  1028.                 return eFileLoadDiskError;
  1029.             }
  1030.  
  1031.         /*   4-byte little endian wave table name length descriptor */
  1032.         StringTemp = WaveTableObjectGetNameCopy(WaveTableObj);
  1033.         if (StringTemp == NIL)
  1034.             {
  1035.                 return eFileLoadOutOfMemory;
  1036.             }
  1037.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1038.             {
  1039.                 ReleasePtr(StringTemp);
  1040.                 return eFileLoadDiskError;
  1041.             }
  1042.  
  1043.         /*   n-byte name string (line feed = 0x0a) */
  1044.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1045.             {
  1046.                 ReleasePtr(StringTemp);
  1047.                 return eFileLoadDiskError;
  1048.             }
  1049.         ReleasePtr(StringTemp);
  1050.  
  1051.         /*   4-byte little endian wave table formula length descriptor */
  1052.         StringTemp = WaveTableObjectGetFormulaCopy(WaveTableObj);
  1053.         if (StringTemp == NIL)
  1054.             {
  1055.                 return eFileLoadOutOfMemory;
  1056.             }
  1057.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1058.             {
  1059.                 ReleasePtr(StringTemp);
  1060.                 return eFileLoadDiskError;
  1061.             }
  1062.  
  1063.         /*   n-byte formula string (line feed = 0x0a) */
  1064.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1065.             {
  1066.                 ReleasePtr(StringTemp);
  1067.                 return eFileLoadDiskError;
  1068.             }
  1069.         ReleasePtr(StringTemp);
  1070.  
  1071.         /*   4-byte little endian large integer encoded test attack duration. */
  1072.         /*       large integer coded decimal is decimal * 1000000 with a */
  1073.         /*       range of -1999.999999 to 1999.999999 */
  1074.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1075.             Double2LargeBCD(WaveTableObjectGetTestAttack(WaveTableObj))))
  1076.             {
  1077.                 return eFileLoadDiskError;
  1078.             }
  1079.  
  1080.         /*   4-byte little endian large integer encoded test decay duration. */
  1081.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1082.             Double2LargeBCD(WaveTableObjectGetTestDecay(WaveTableObj))))
  1083.             {
  1084.                 return eFileLoadDiskError;
  1085.             }
  1086.  
  1087.         /*   4-byte little endian test frequency fractional portion */
  1088.         /*       unsigned; divide by 2^32 to get the actual fraction */
  1089.         FrequencyTemp = WaveTableObjectGetTestPitch(WaveTableObj);
  1090.         if (!WriteBufferedUnsignedLongLittleEndian(Output,
  1091.             (unsigned long)((FrequencyTemp - (long)FrequencyTemp) * 4294967296.0L)))
  1092.             {
  1093.                 return eFileLoadDiskError;
  1094.             }
  1095.  
  1096.         /*   4-byte little endian test frequency integer portion */
  1097.         /*       total test frequency should be between 0.01 and 1e6 */
  1098.         if (!WriteBufferedSignedLongLittleEndian(Output,(long)FrequencyTemp))
  1099.             {
  1100.                 return eFileLoadDiskError;
  1101.             }
  1102.  
  1103.         /*   4-byte little endian test sampling rate */
  1104.         /*       should be between 100 and 65535 */
  1105.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1106.             WaveTableObjectGetTestSamplingRate(WaveTableObj)))
  1107.             {
  1108.                 return eFileLoadDiskError;
  1109.             }
  1110.  
  1111.         /*   4-byte little endian number of tables */
  1112.         NumberOfTables = WaveTableObjectGetNumTables(WaveTableObj);
  1113.         if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfTables))
  1114.             {
  1115.                 return eFileLoadDiskError;
  1116.             }
  1117.  
  1118.         /*   4-byte little endian number of frames per table */
  1119.         /*       must be an integral power or 2 between 2 and 65536 */
  1120.         NumberOfFrames = WaveTableObjectEntriesPerTable(WaveTableObj);
  1121.         if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfFrames))
  1122.             {
  1123.                 return eFileLoadDiskError;
  1124.             }
  1125.  
  1126.         /*   1-byte number of bits specifier */
  1127.         /*       must be 8 or 16 */
  1128.         NumberOfBits = WaveTableObjectGetNumBits(WaveTableObj);
  1129.         switch (NumberOfBits)
  1130.             {
  1131.                 default:
  1132.                     EXECUTE(PRERR(ForceAbort,"WaveTableObjectWriteDataOut:  bad number of bits"));
  1133.                     break;
  1134.                 case eSample8bit:
  1135.                     if (!WriteBufferedUnsignedChar(Output,8))
  1136.                         {
  1137.                             return eFileLoadDiskError;
  1138.                         }
  1139.                     break;
  1140.                 case eSample16bit:
  1141.                     if (!WriteBufferedUnsignedChar(Output,16))
  1142.                         {
  1143.                             return eFileLoadDiskError;
  1144.                         }
  1145.                     break;
  1146.             }
  1147.  
  1148.         /*   n-byte sample data for the wave table */
  1149.         /*       data is stored as follows:  each table is stored consecutively starting */
  1150.         /*       with the table numbered 0.  in each table, each sample frame is stored */
  1151.         /*       consecutively as a signed 2s complement value.  8-bit sample frames */
  1152.         /*       use 1 byte each.  16-bit sample frames use 2 bytes and are stored little */
  1153.         /*       endian. */
  1154.         switch (NumberOfBits)
  1155.             {
  1156.                 default:
  1157.                     EXECUTE(PRERR(ForceAbort,"WaveTableObjectWriteDataOut:  bad number of bits"));
  1158.                     break;
  1159.                 case eSample8bit:
  1160.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  1161.                         {
  1162.                             long                            Index;
  1163.                             signed char*            Slice;
  1164.  
  1165.                             Slice = (signed char*)WaveTableObjectGetRawSlice(WaveTableObj,Scan);
  1166.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  1167.                                 {
  1168.                                     PRNGCHK(Slice,&(Slice[Index]),sizeof(Slice[Index]));
  1169.                                     if (!WriteBufferedSignedChar(Output,Slice[Index]))
  1170.                                         {
  1171.                                             return eFileLoadDiskError;
  1172.                                         }
  1173.                                 }
  1174.                         }
  1175.                     break;
  1176.                 case eSample16bit:
  1177.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  1178.                         {
  1179.                             long                            Index;
  1180.                             signed short*            Slice;
  1181.  
  1182.                             Slice = (signed short*)WaveTableObjectGetRawSlice(WaveTableObj,Scan);
  1183.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  1184.                                 {
  1185.                                     PRNGCHK(Slice,&(Slice[Index]),sizeof(Slice[Index]));
  1186.                                     if (!WriteBufferedSignedShortLittleEndian(Output,Slice[Index]))
  1187.                                         {
  1188.                                             return eFileLoadDiskError;
  1189.                                         }
  1190.                                 }
  1191.                         }
  1192.                     break;
  1193.             }
  1194.  
  1195.         return eFileLoadNoError;
  1196.     }
  1197.  
  1198.  
  1199. /* mark wave table object as saved */
  1200. void                                    WaveTableObjectMarkAsSaved(WaveTableObjectRec* WaveTableObj)
  1201.     {
  1202.         CheckPtrExistence(WaveTableObj);
  1203.         if (WaveTableObj->WaveTableWindow != NIL)
  1204.             {
  1205.                 WaveTableWindowWritebackModifiedData(WaveTableObj->WaveTableWindow);
  1206.             }
  1207.         WaveTableObj->DataModified = False;
  1208.     }
  1209.